
// Promise改进
new Promise((resolve, reject) => {
  resolve('hello')
}).then(res => {
  return res + ' lagou'
}).then(res => {
  console.log(res + ' I love u')
})

// 第一题
let isLastInStock = fp.flowRight(v => fp.prop('in_stock', v), fp.last)

// 第二题
let getFirstName = fp.flowRight(v => fp.prop('name', v), fp.first)

// 第三题

// 第四题
const first = array => fp.first(array)
const toUpper = str => str.toLowerCase()
const replace = str => str.replace(/\W+/g, '_')
const getValue = fp.flowRight(replace, toUpper, first)
console.log(getValue(['Hello World']))


// 第一题
let ex1 = Container.of(maybe._value).map(array => {
  let count = 0
  array.map(item => count += item)
  return count
})._value

// 第二题
let ex2 = Maybe.of(xs._value).map(array => {
  return fp.first(array)
})._value

// 第三题
let ex3 = Container.of(user).map(user => {
  const name = safeProp('name')(user)._value
  const label = fp.first(name)
  return {
    name, label
  }
})._value

// 第四题
let ex4 = Maybe.of(null).map(v => {
  return parseInt(v)
})._value

// promise源码
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const PENDDING = 'pendding'

class MyPromise {

  // 初始化Promise状态
  status = PENDDING

  // 成功结果
  sucResult = undefined

  // 失败原因
  failReason = undefined

  // 成功回调
  sucCallback = []

  // 失败回调
  failCallback = []

  constructor(execute) {
    try {
      execute(this.resolve, this.reject)
    } catch (error) {
      this.reject(error)
    }
  }

  resolve = result => {
    // 状态冻结
    if (this.status !== PENDDING) return
    this.status = FULLFILLED

    this.sucResult = result

    // 链式调用then方法回调
    while(this.sucCallback.length) this.sucCallback.shift()()
  }

  reject = reason => {
    // 状态冻结
    if (this.status !== PENDDING) return
    this.status = REJECTED

    this.failReason = reason

    // 链式调用then方法回调
    while(this.failCallback.length) this.failCallback.shift()()
  }

  then (successCallback, failCallback) {
    successCallback = successCallback ? successCallback : result => result
    failCallback = failCallback ? failCallback : reason => reason
    const xPromise = new XPromise((resolve, reject) => {
      if (this.status === FULFILLED) {
        // 获取当前xPromise对象
        setTimeout(() => {
          try {
            const sucResult = successCallback(this.sucResult)
            isPromise(xPromise, sucResult, resolve, reject)
          } catch (error) {
            reject(error)
          }
        }, 0)
        return
      }
      if (this.status === REJECTED) {
        // 获取当前xPromise对象
        setTimeout(() => {
          try {
            const failResult = failCallback(this.failReason)
            isPromise(xPromise, failResult, resolve, reject)
          } catch (error) {
            reject(error)
          }
        }, 0)
        return
      }
      // 异步等待状态，临时存储成功失败回调方法
      this.sucCallback.push(() => {
        setTimeout(() => {
          try {
            const sucResult = successCallback(this.sucResult)
            isPromise(xPromise, sucResult, resolve, reject)
          } catch (error) {
            reject(error)
          }
        }, 0)
      })
      this.failCallback.push(() => {
        setTimeout(() => {
          try {
            const sucResult = failCallback(this.failReason)
            isPromise(xPromise, sucResult, resolve, reject)
          } catch (error) {
            reject(error)
          }
        }, 0)
      })
    })
    return xPromise
  }

  static all (array) {
    const result = []
    let count = 0
    return new XPromise((resolve, reject) => {
      function addData (key, value) {
        result[key] = value
        count++
        if (count === array.length) resolve(result)
      }

      for (let i = 0; i < array.length; i++) {
        if (array[i] instanceof XPromise) {
          array[i].then(v => addData(i, v), reason => reject(reason))
        } else {
          addData(i, array[i])
        }
      }
    })
  }

  static resolve (value) {
    if (value instanceof XPromise) return value
    return new XPromise(resolve => resolve(value))
  }

  catch (failCallback) {
    return this.then(undefined, failCallback)
  }

  finally (callback) {
    return this.then(value => {
      return MyPromise.resolve(callback()).then(() => value);
    }, reason => {
      return MyPromise.resolve(callback()).then(() => { throw reason })
    })
  }
  
}

function isPromise(p, promise, resolve, reject) {
  // 处理then方法返回自己promise，捕捉链式循环调用
  if (p === promise) return reject(new TypeError('Chaining cycle detedcted for promise #<Promise>'))
  if (promise instanceof XPromise) {
    // then返回的是promise
    promise.then(resolve, reject)
  } else {
    // 普通对象
    resolve(promise)
  }
}